package com.shop.wk.filter.global;

import com.alibaba.fastjson.JSONObject;
import com.shop.wk.common.constant.HttpCode;
import java.nio.charset.StandardCharsets;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * @author 日月星辰
 * @date 2020/12/27 3:40
 * @description 义全局异常处理， 404异常应该在Filter中判断url是否在数据库、redis中注册
 */
@Slf4j
public class JsonExceptionHandler implements ErrorWebExceptionHandler {

  @Override
  public Mono<Void> handle(ServerWebExchange serverWebExchange, Throwable throwable) {
    ServerHttpRequest request = serverWebExchange.getRequest();
    JSONObject reslut = new JSONObject();
    reslut.put("timestamp", System.currentTimeMillis());
    reslut.put("code", HttpCode.FAIL);
    reslut.put("path", request.getPath().value());
    if (throwable instanceof NotFoundException) {
      reslut.put("message", "不存在的路径");
    } else if (throwable instanceof ResponseStatusException) {
      reslut.put("message", "服务内部异常");
    } else {
      reslut.put("message", "未知");
    }
    reslut.put("data", throwable.getMessage());
    //记录日志
    log.error("[全局系统异常]\r\n请求路径：{}\r\n异常记录：{}", request.getPath().value(), throwable.getMessage());
    return writeJsonResponse(reslut, serverWebExchange.getResponse());
  }

  private Mono<Void> writeJsonResponse(JSONObject reslut, ServerHttpResponse response) {
    response.setStatusCode(HttpStatus.OK);
    response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
    DataBuffer buffer = response.bufferFactory().wrap(reslut.toString().getBytes(StandardCharsets.UTF_8));
    return response.writeWith(Mono.just(buffer));
  }
}
